﻿#include <iostream>
#include "core/app_manager.h"
#include "core/async_listener.h"

using namespace vz;

class App1 : public AppInterface,
  public sigslot::has_slots<> {
 public:
  typedef scoped_refptr<App1> Ptr;
  App1(const std::string& app_name)
    : AppInterface(app_name) {
    send_data_ = new char[10240];
    memset(send_data_, 65, 10240);
  }

  bool OnPreInit() {
    LOG(LS_INFO) << "OnPreInit";
    return true;
  }

  bool OnInit() {
    LOG(LS_INFO) << "OnInit";
    return true;
  }

  bool OnRun() {
    LOG(LS_INFO) << "OnRun";

    listener_ = event_service_->CreateListener();
    listener_->SignalAcceptEvent.connect(this, &App1::OnAcceptEvent);
    SocketAddress address("0.0.0.0", 6756);
    listener_->Start(address);
    return true;
  }

  void OnAppMessage(Message* msg) {
    LOG(LS_INFO) << "OnAppMessage";
    if (msg->message_id == 101) {
      ScopedRefMessageData<AsyncPacketSocket> *data =
        reinterpret_cast<ScopedRefMessageData<AsyncPacketSocket>*>(msg->pdata);
      AsyncPacketSocket::Ptr socket = data->data();
      int res = socket->SendPacket(2, send_data_, 10240);
      if (res < 0) {
        LOG(LS_ERROR) << "Send packet failed! error: " << socket->GetError();
        delete data;
        data = NULL;
      } else {
        event_service_->PostDelayed(40, this, 101, data);
      }


    }
  }

 private:
  void OnAcceptEvent(AsyncListener::Ptr listener,
                     AsyncPacketSocket::Ptr socket) {
    LOG(LS_INFO) << "New connect";
    sockets_.push_back(socket);
    socket->SignalPacketEvent.connect(this, &App1::OnPacketEvent);
    socket->SignalCloseEvent.connect(this, &App1::OnCloseEvent);
  }

  void OnPacketEvent(AsyncPacketSocket::Ptr socket, uint16 cmd, const char* data, uint32 data_size) {
    LOG(LS_INFO) << "New packet";
    if (cmd == 1) {
      ScopedRefMessageData<AsyncPacketSocket> *data =
        new ScopedRefMessageData<AsyncPacketSocket>(socket);
      event_service_->Post(this, 101, data);
    }
  }

  void OnCloseEvent(AsyncPacketSocket::Ptr socket, int error) {
    LOG(LS_ERROR) << "Socket closed! error: " << error;
    sockets_.remove(socket);
  }

 private:
  AsyncListener::Ptr listener_;
  std::list<AsyncPacketSocket::Ptr> sockets_;
  char *send_data_;
};

int main(int argc, char *argv[]) {
  AppManager::Ptr manager(new RefCountedObject<AppManager>());
  App1::Ptr app1(new RefCountedObject<App1>("App1"));
  manager->Register(app1);

  manager->Run();

  return 0;
}
